package com.pro.framework.api.util;

import com.pro.framework.api.database.page.PageResultCursor;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Function;

@Slf4j
public class PageUtil {
    /**
     * 游标分页 一直下一页直到查询完 拼接一起返回
     */
    public static <T> List<T> loadAllCursorPage(Function<String, PageResultCursor<T>> pageFun, Function<PageResultCursor<T>, Boolean> breakFun, boolean failThrow) {
        // 初始化
        List<T> list = new ArrayList<>();
        String nextPageToken = null;
        while (true) {
            // 获取当前页数据
            PageResultCursor<T> pageResult = null;
            try {
                pageResult = pageFun.apply(nextPageToken);
            } catch (Exception e) {
                if (failThrow) {
                    throw e;
                } else {
                    log.warn("分页加载第 nextPageToken={} 页失败 \n{}", nextPageToken, ExceptionUtil.logThrowable(e));
                    break;
                }
            }
            List<T> subList = pageResult.getList();
            nextPageToken = pageResult.getNextPageToken();
            // 添加当前页数据到结果列表
            list.addAll(subList);
            if (breakFun.apply(pageResult)) {
                break;
            }
        }
        return list;
    }

    public static <T> List<T> loadAllCursorPage(Function<String, PageResultCursor<T>> pageFun, Integer pageSize, boolean failThrow) {
        return loadAllCursorPage(pageFun, rs -> rs.getList().size() < pageSize || rs.getNextPageToken() == null, failThrow);
    }

//    /**
//     * 最简分页加载工具：支持 pageNum + pageSize 分页接口，支持 failFast 开关
//     *
//     * @param requestExecutor 请求函数，根据页码获取响应
//     * @param extractList     响应提取函数，从响应中提取数据列表
//     * @param pageSize        每页大小
//     */
//    public static <RESP, T> List<T> loadAllPage(
//            Function<Integer, RESP> requestExecutor,
//            Function<RESP, List<T>> extractList,
//            int pageSize
//    ) {
//        return loadAllPage(
//                requestExecutor,
//                extractList,
//                pageSize,
//                true
//        );
//    }

    /**
     * 最简分页加载工具：支持 pageNum + pageSize 分页接口，支持 failThrow 开关
     *
     * @param requestExecutor 请求函数，根据页码获取响应
     * @param extractList     响应提取函数，从响应中提取数据列表
     * @param pageSize        每页大小
     * @param failThrow       是否失败即中断（true: 遇异常抛出；false: 遇异常返回已加载部分）
     */
    public static <RESP, T> List<T> loadAllPage(
            Function<Integer, RESP> requestExecutor,
            Function<RESP, List<T>> extractList,
            int pageSize,
            boolean failThrow
    ) {
        List<T> result = new ArrayList<>();
        int pageNum = 1;
        while (true) {
            try {
                RESP resp = requestExecutor.apply(pageNum);
                List<T> data = extractList.apply(resp);
                if (data == null || data.isEmpty()) break;
                result.addAll(data);
                if (data.size() < pageSize) break;
                pageNum++;
            } catch (Exception e) {
//                if (e instanceof IBreakException) {
//                    throw e;
//                } else
                if (failThrow) {
                    throw e;
                } else {
                    log.warn("分页加载第 {} 页失败 \n{}", pageNum, ExceptionUtil.logThrowable(e));
                    break;
                }
            }
        }
        return result;
    }

    /**
     * 支持游标分页加载工具
     */
    public static <RESP, T, CURSOR> List<T> loadAllByCursor(
            Function<CURSOR, RESP> requestExecutor,
            Function<RESP, List<T>> extractList,
            Function<RESP, CURSOR> nextCursorExtractor,
            boolean failThrow
    ) {
        List<T> result = new ArrayList<>();
        CURSOR cursor = null;

        while (true) {
            try {
                RESP resp = requestExecutor.apply(cursor);
                List<T> data = extractList.apply(resp);
                if (data == null || data.isEmpty()) break;
                result.addAll(data);
                CURSOR nextCursor = nextCursorExtractor.apply(resp);
                if (nextCursor == null || Objects.equals(nextCursor, cursor)) break;
                cursor = nextCursor;
            } catch (Exception e) {
                log.warn("分页加载失败，参数={}", cursor, e);
                if (failThrow) {
                    throw e;
                } else {
                    break;
                }
            }
        }
        return result;
    }
    /**
     * 从列表中截取分页后的子列表
     *
     * @param list               原始列表
     * @param pageNumOrPageToken 页码（从1开始）或分页令牌（这里只做页码处理）
     * @param pageSize           每页数量
     * @param <T>                列表元素类型
     * @return 当前页的数据列表，可能为空列表，但不会为 null
     */
    public static <T> List<T> subListPage(List<T> list, String pageNumOrPageToken, Integer pageSize) {
        int pageNum = Integer.parseInt(pageNumOrPageToken);
        int fromIndex = (pageNum - 1) * pageSize;
        int toIndex = pageNum * pageSize;
        int size = list.size();
        if (size <= fromIndex) {
            return Collections.emptyList();
        }
        return list.subList(fromIndex, Math.min(size, toIndex));
    }

    public static <T> PageResultCursor<T> subListCursor(List<T> list, String cursorStr, int pageSize) {
        int cursor = 0;
        if (cursorStr != null && !cursorStr.isBlank()) {
            try {
                cursor = Integer.parseInt(cursorStr);
            } catch (NumberFormatException e) {
                cursor = 0; // 容错处理
            }
        }

        int fromIndex = cursor;
        int toIndex = Math.min(cursor + pageSize, list.size());

        if (fromIndex >= list.size()) {
            return new PageResultCursor<>(Collections.emptyList(), null);
        }

        List<T> subList = list.subList(fromIndex, toIndex);
        String nextCursor = (toIndex < list.size()) ? String.valueOf(toIndex) : null;

        return new PageResultCursor<>(subList, nextCursor);
    }

}
